#pragma once

#include <string>
#include <algorithm>
#include <iostream>
//#include "QueryEvaluator.h"
#include "QueryTable.h"
#include "RelationshipTable.h"
#include "RelationshipType.h"
#include "DesignEntityType.h"
#include "ConstraintTableType.h"
#include "QueryExpressionParser.h"


using namespace std;


// ** How to use QueryPreprocessor: see int main()
// **	preprocess() returns true if the query is syntaxically correct
// **   info is stored inside the query table that is passed to the constructor
// ** Assume queries are case sensitive
// ** Right now does not support pattern
 
class QueryPreprocessor {
	public:
		/// The constructor for query preprocessor. It takes in a reference to a Query Expression Parser, and instantiates a new object
		QueryPreprocessor(QueryExpressionParser *expressionParser);
		/// This method preprocess the query. It will return false if the query is syntaxically incorrect. It will return true if the query is correct
		/// and it will store parsed results into queryTable.
		bool preprocess(string queryString,QueryTable* queryTable);

	private:
		string str;
		QueryTable* mQueryTable;
		RelationshipTable mRelValidationTable;
		vector<string> mTokens;
		int mIndex, mTokensNum;
		QueryExpressionParser* mExpressionParser;
		void removeRedundantSynonyms();
		bool match(string matcher, string matchee);
		bool matchDeclaration();
		bool matchSuchThatClause();
		bool matchRelCond();
		bool matchPattern();
		bool matchPatternCond();
		bool matchPatternClause();
		bool matchWithClause();
		bool matchAttrCond();
		bool matchAttrCompare();
		bool isLetter(char ch);
		bool isDigit(char ch);
		bool isNumber(string st);
		bool isName(string str);
		bool isZero(string st);
		bool matchResultClause();
		bool matchCaseless(string matcher, string matchee);
		RelationshipArgumentType convertDEToRelArg(DesignEntityType);
		DesignEntityType matchSynonym(string matcher);
		ConstraintType determineConstraintType(RelationshipArgumentType argType, ConstraintAttrType attrType);
		ConstraintAttrType determineConstraintAttrType (string attr);
		bool matchIdent(string symbol);
		bool matchQueryEnd();
		bool matchRelRef();
		string trimFrontEndSpaces(string str);
		RelationshipArgumentType matchRelUnderscore(RelationshipType type, int pos);
		RelationshipArgumentType matchRelArgType(string *st);
		DesignEntityType matchDesignEntity(string symbol);
		RelationshipType matchRelType(string str);
		RelationshipType matchRelTypeModifiesUsesProc (RelationshipType type, RelationshipArgumentType arg1Type, RelationshipArgumentType arg2Type);
		bool isValidResultSynonym(std::string*, ConstraintAttrType*);
		bool checkIfContainEquivalent(ConstraintEntry);
		void processEquivalentSynonyms(std::string s1, std::string s2);
		//~QueryPreprocessor(void);
		// Preprocesses the query string into a query tree,
		// and then calls the Query Evaluator to evaluate the query
		// with the query tree. 
		// (The Query Evaluator will send the query result to the
		// 	Query Result Projector)
		
};